import { _decorator, Animation, Color, Component, director, EventTouch, game, Graphics, instantiate, Label, Node, NodeEventType, Prefab, ProgressBar, RigidBody2D, Sprite, UITransform, Vec2, Vec3 } from 'cc';
import { CacheManager } from '../manager/CacheManager';
import MathUtils from '../utils/MathUtils';
import Mgr from '../manager/Mgr';
import { Player } from './entity/Player';
import { PlayerCamera } from './PlayerCamera';
import { UIModuleEnum } from '../enum/UIDefine';
import { PlayerVo } from './vo/PlayerVo';
import { EventManager } from '../manager/EventManager';
import { EventEnum } from '../enum/EventEnum';
import { Enemy } from './entity/Enemy';
import { ShakeUtils } from '../utils/ShakekUtils';
import { ShakeConst } from '../utils/shake/ShakeConst';
import { SDK } from '../SDK/SDK';
import { AlertType, AlertView } from '../common/alert/AlertView';
const { ccclass, property } = _decorator;

@ccclass('GameSceneView')
export class GameSceneView extends Component {
    public static EnemyPool:Enemy[] = [];
    public static instance:GameSceneView;
    @property(Node) container:Node = null;
    @property(Node) battleLayer:Node = null;
    @property(Node) enemyContainer:Node = null;
    @property(Node) touchArea:Node = null;
    @property(Player) player:Player = null;
    @property(PlayerCamera) playerCamera:PlayerCamera = null;
    @property(Node) imgArrow:Node = null;
    @property(Node) imgBody:Node = null;
    @property(UITransform) imgArrowTf:UITransform = null;
    @property(Graphics) graphics:Graphics = null;
    @property(RigidBody2D) rigidbody:RigidBody2D = null;
    @property(ProgressBar) hpBar:ProgressBar;
    @property(Node) btnStart:Node = null;
    @property(Node) btnPause:Node = null;
    @property(Label) txtPause:Label = null;
    @property(Animation) animReady:Animation = null;
    @property(Animation) animCombo:Animation = null;
    @property(Label) txtCombo:Label = null;
    @property(Sprite) imgCircleHp:Sprite = null;
    @property(Sprite) imgHpBar:Sprite = null;
    private _circleHpColor:Color;
    private _killNum:number = 0;
    private _comboKill:number = 0;
    private _comboTime:number = 3;
    
    private _startPos:Vec3;
    private _endPos:Vec3;
    private _evtTouchPos:Vec3;
    
    private _forceVec:Vec2;
    private _forceScaler:number = 10;
    private _beginShoot:boolean = false;
    private _shooting:boolean = false;

    private _deltaTime:number = 0;
    private _playerVo:PlayerVo;
    private _enemys:Enemy[];
    protected onLoad(): void {
        GameSceneView.instance = this;
        this._circleHpColor = new Color(0,255,0);
        this.initUI();
        this.player.node.active = false;
        CacheManager.game.player = this.player;
    }

    protected initUI(){
        this._forceVec = new Vec2();
        this._startPos = new Vec3();
        this._endPos = new Vec3(); 
        this._evtTouchPos = new Vec3();
        this._enemys = [];

        this.btnStart.on(NodeEventType.TOUCH_END,()=>{
            this.btnStart.active = false;
            CacheManager.game.startGame();
        });

        this.btnPause.on(NodeEventType.TOUCH_END,()=>{
            let pause = CacheManager.game.isPause;
            CacheManager.game.setPause(!pause);
        });

        // this.touchArea.active = false;
        this.touchArea.on(NodeEventType.TOUCH_START,(evt:EventTouch)=>{
            if(!CacheManager.game.isStart()) return;
            let touchPos = evt.getUIStartLocation(); 
            this.touchStart(touchPos);
        });
    
        this.touchArea.on(NodeEventType.TOUCH_CANCEL,()=>{
            if(!CacheManager.game.isStart()) {
                this._beginShoot = false;
                return;
            }
            this.touchEnd();
        });
    
        this.touchArea.on(NodeEventType.TOUCH_END,()=>{
            if(!CacheManager.game.isStart()) {
                this._beginShoot = false;
                return;
            }
            this.touchEnd();
        });
    
        this.touchArea.on(NodeEventType.TOUCH_MOVE,(event:EventTouch)=>{
            let pos = event.getUIDelta();
            this.touchMove(pos.x,pos.y);
        });

        EventManager.addListener(EventEnum.OnGameStart,()=>{
            this.onGameStart();
        },this);
        EventManager.addListener(EventEnum.OnGameOver,()=>{
            this.onGameOver();
        },this);

        EventManager.addListener(EventEnum.OnEnemyDeath,(enemy:Enemy)=>{
            let idx = this._enemys.indexOf(enemy);
            if(idx >= 0){
                this._enemys.splice(idx,1);
                GameSceneView.EnemyPool.push(enemy);
                this._killNum++;
                this._comboKill++;
                if(this._comboKill >= 2) {
                    this._comboTime = 3;
                    this.txtCombo.node.active = true;
                    this.txtCombo.string = `X${this._comboKill}`;
                    this.animCombo.play();
                    let timeScale = CacheManager.game.timeScale;
                    this.animCombo.defaultClip.speed = timeScale > 0 ? timeScale : 1;
                    console.log("combo X" + this._comboKill)
                }
            }
        },this);
        EventManager.addListener(EventEnum.OnGameStateUpdate,()=>{
            this.updateGameState();
            if(CacheManager.game.isPause){
                AlertView.show("暂停游戏！",{canClose:true},()=>{
                    CacheManager.game.setPause(false);
                },[AlertType.YES],["继续游戏"]);
            }
        },this);
        EventManager.addListener(EventEnum.onGameSpeedUpdate,()=>{
            let timeScale = CacheManager.game.timeScale;
            this.animCombo.defaultClip.speed = timeScale > 0 ? timeScale : 1;
        },this);
	}

    protected update(dt: number): void {
        if(CacheManager.game.isStart()) {
            if(!this._playerVo) return;
            let fixedDt = dt * CacheManager.game.timeScale;
            this._deltaTime += fixedDt;
            this._comboTime -= fixedDt;
            if(this._comboTime < 0 && this._comboKill > 1) {
                this.resetCombo();
            }
            if(this._deltaTime >= 5){
                this._deltaTime = 0;
                this.createEnemy(5);
                console.log("生成敌人");
            }
            
            this._playerVo.hp -= fixedDt * this._playerVo.hpRatio;
            let progress = this._playerVo.hp / this._playerVo.maxHp;
            this.hpBar.progress = progress;
            this.imgCircleHp.fillRange = -progress;
            if(progress >= 0.5){
                this._circleHpColor.r = 255 * ((1 - progress) / 0.5);1
                this._circleHpColor.g = 255;
            }
            else{
                this._circleHpColor.r = 255;
                this._circleHpColor.g = 255 * (progress / 0.5);
            }
            this.imgCircleHp.color = this._circleHpColor;
            this.imgHpBar.color = this._circleHpColor;
        }
    }

    private resetCombo() {
        this.txtCombo.node.active = false;
        this._comboKill = 0;
        console.log("重置combo")
    }

    private updateGameState(){
        let isPause = CacheManager.game.isPause;
        if(isPause){
            this.txtPause.string = "开始";
        }
        else {
            this.txtPause.string = "暂停";
        }
    }

    private createEnemy(num:number){
        if(this._enemys.length < 50){
            let pos = this.player.node.getPosition();
            Mgr.loader.LoadUIPrefab(UIModuleEnum.main,"Enemy",(prefab:Prefab)=>{
                let pts = MathUtils.generatePoints2(pos.x,pos.y,1000,num,150);
                console.log("生成数量：" + pts.length)
                for(let i = 0; i < pts.length; i++){
                    let pt = pts[i];
                    let posX = pt[0];
                    let posY = Math.max(pt[1],MathUtils.getRandom(100,500));
                    let enemy = GameSceneView.EnemyPool.pop();
                    if(!enemy){
                        let node = instantiate(prefab);
                        enemy = node.getComponent(Enemy);
                    }
                    enemy.node.setPosition(posX,posY,0);
                    enemy.init();    
                    this.enemyContainer.addChild(enemy.node);
                    enemy.node.name = i+"";
                    this._enemys.push(enemy);
                }
            });
        }
    }

    private onGameStart(){
        this.createEnemy(5);
        this.btnStart.active = false;
        this.animReady.stop();
        this._playerVo = CacheManager.game.playerVo;
        this._beginShoot = false;
        this.player.init();
    }

    private onGameOver(){
        console.log("游戏结束")
        this.touchEnd();
        this.btnStart.active = true;
        this.animReady.play();
        for(let e of this._enemys){
            e.death();
            GameSceneView.EnemyPool.push(e);
        }
        this._enemys = [];
        Mgr.soundMgr.play("laser9",false);
        ShakeUtils.shakeScene(0,ShakeConst.TYPE_SHAKE,3);
        SDK.vibrateShort();
    }

    private touchStart(pos){
        if(this._beginShoot || this._shooting) return;
        this._beginShoot = true;
        this._playerVo.hpRatio = 20;
        CacheManager.game.setGameSpeed(0.1);
        this.rigidbody.getLocalCenter(this._startPos);
        this._endPos.x = pos.x - 540;
        this._endPos.y = pos.y - 1080;

        // this._graphics.clear();
        // this._graphics.fillRect(pos.x - 540,pos.y - 1080,50,50);
        // this._graphics.fill();
        // this._graphics.fillRect(this._startPos.x,this._startPos.y,10,10);
        // this._graphics.fill();
        // //pos是以屏幕左下角为原点，所以减去屏幕宽高的一半，为当前container下的实际触摸点
        
        // this._graphics.moveTo(this._startPos.x,this._startPos.y);
        // this._graphics.lineTo(this._endPos.x,this._endPos.y);
        // // this._graphics.close();
        // this._graphics.stroke();
        // this._graphics.fill();

        this.imgArrow.active = true;
        this.updateDis();

        // this._imgArrow.setPosition(this._startPos.x,this._startPos.y);
    }

    private touchMove(deltaX:number,deltaY:number){
        if(this._beginShoot){
            let endX = this._endPos.x + deltaX;
            let endY = this._endPos.y + deltaY;
            this._endPos.x = endX;
            this._endPos.y = endY; 
            this.updateDis();
        }
    }

    private touchEnd(){
        if(!this._beginShoot) return;
        this._playerVo.hpRatio = 5;
        CacheManager.game.setGameSpeed(1);
        this._beginShoot = false;
        this.imgArrow.active = false;
        if(this._endPos.x == this._startPos.x && this._endPos.y == this._startPos.y){
            this._endPos.x = 0;
            this._endPos.y = 1;
        }
        else {
            this._endPos.subtract(this._startPos);
        }
        this.shoot();
    }

    private updateDis(){
        let offsetY = this.playerCamera.node.position.y - this.player.node.position.y;
        let dis = MathUtils.getDistance(this._startPos.x,this._startPos.y,this._endPos.x,this._endPos.y + offsetY);
        let cameraRatio = this.playerCamera.camera.orthoHeight / 1080;
        this.imgArrowTf.setContentSize(40,dis * cameraRatio);
        this._forceScaler = dis;

        let angle = MathUtils.getAngle2(this._startPos.x,this._startPos.y,this._endPos.x,this._endPos.y) - 90;
        this.player.updateAngle(angle);
        // this.imgArrow.setRotationFromEuler(0,0,angle);
        // this.imgBody.setRotationFromEuler(0,0,angle);
    }

    private shoot(){
        if(!CacheManager.game.isStart()) return;
        if(this._shooting) return;
        // this._shooting = true;
        this._beginShoot = false;
        Mgr.soundMgr.play("ball_shoot",false);
        // this._rigidbody.applyLinearImpulseToCenter(this._forceVec,true);
        this._forceVec.x = this._endPos.x;
        this._forceVec.y = this._endPos.y;
        this._forceVec.normalize();
        this._forceVec.multiplyScalar(50 + this._forceScaler*0.5);
        console.log("shoot:" + this._forceScaler)
        this.player.shoot(this._forceVec);
        // this._rigidbody.applyLinearImpulseToCenter(this._forceVec,true);
        // console.log("force:" + this._forceScaler)

        // this._curDir.x = force.x;
        // this._curDir.y = force.y;
        // this._curDir.normalize();
        // // this.updateAngle();
    }
}



